// Copyright (c) 2023 CHANGLEI. All rights reserved.

// ignore_for_file: unused_element

part of 'ui_decorator.dart';

const _loginButtonMargin = 46.5;
const _loginButtonHeight = 45.0;

/// Created by changlei on 2023/8/14.
///
/// [TXLoginUIModel]
final class UIModel extends UIDecorator {
  /// [TXLoginUIModel]
  const UIModel({
    this.appLanguageType,
    this.appPrivacy,
    this.appPrivacyDemo,
    this.appPrivacyOriginLR,
    this.authWindow,
    this.brandLabelTextSize,
    this.checkBoxWH,
    this.checkTipText,
    this.checkboxOffsetX,
    this.checkboxOffsetY,
    this.checkboxOffsetYB,
    this.checkedImg,
    this.controllerSize,
    this.cornerRadius,
    this.customBackgroundView,
    this.customOtherLoginViews,
    this.customTopLoginView,
    this.edgeWindow,
    this.faceOrientation,
    this.iconImage,
    this.ifCreateCustomView,
    this.ignorePrivacyState,
    this.isShowLoginLoadingView,
    this.logBtnHeight,
    this.logBtnOffsetY,
    this.logBtnOriginLR,
    this.logBtnText,
    this.loginBtnColors,
    this.loginBtnImgs,
    this.loginLoadingView,
    this.logoFrame,
    this.logoHidden,
    this.modalPresentationStyle,
    this.modalTransitionStyle,
    this.numberOffsetX,
    this.numberTextAttributes,
    this.presentAnimated,
    this.presentType,
    this.privacyColor,
    this.privacyLabelOffsetY,
    this.privacyObserve,
    this.privacyState,
    this.privacyUncheckAnimation,
    this.scaleH,
    this.scaleW,
    this.sloganHidden,
    this.sloganLabelOffsetY,
    this.sloganTextColor,
    this.statusBarStyle,
    this.txMobliNumberOffsetY,
    this.uncheckedImg,
    this.viewBackImg,
    this.webNavColor,
    this.webNavReturnImg,
    this.webNavTitleAttrs,
  });

  /// 适配
  factory UIModel.adaptive(
    BuildContext context, {
    Color textColor = CupertinoColors.label,
    Color? privacyNavBgColor,
    String? privacyContentText,
    ({String name, String url})? userAgreement,
    ({String name, String url})? privacyPolicy,
    UIImage? logo,
    UIImage? background,
    String? welcomeText,
    VoidCallback? onSwitch,
    VoidCallback? onClose,
  }) {
    final mediaQueryData = MediaQueryData.fromView(View.of(context));
    final padding = mediaQueryData.padding;
    final top = padding.top;
    final left = padding.left;
    final right = padding.right;
    final bottom = padding.bottom;
    final size = mediaQueryData.size;
    final width = size.width;
    final height = size.height;
    final orientation = mediaQueryData.orientation;
    double valueOf(double portrait, double landscape) {
      return switch (orientation) {
        Orientation.portrait => portrait,
        Orientation.landscape => landscape,
      };
    }

    final NSAttributedString? appPrivacyDemo;
    if (privacyContentText != null) {
      privacyContentText = privacyContentText.replaceAll(r'$$运营商条款$$', r'&&默认&&');
      if (userAgreement != null) {
        privacyContentText = privacyContentText.replaceAll(userAgreement.name, '《${userAgreement.name}》');
      }
      if (privacyPolicy != null) {
        privacyContentText = privacyContentText.replaceAll(privacyPolicy.name, '《${privacyPolicy.name}》');
      }
      appPrivacyDemo = NSAttributedString(
        string: privacyContentText,
      );
    } else {
      appPrivacyDemo = null;
    }
    final loginButtonSize = Size(
      width - _loginButtonMargin * 2 - left - right,
      _loginButtonHeight,
    );
    return UIModel(
      faceOrientation: false,
      presentAnimated: true,
      logBtnOffsetY: valueOf(height - (488 + top), 40 + bottom),
      logoHidden: true,
      logBtnOriginLR: [_loginButtonMargin + left, _loginButtonMargin + right],
      logBtnHeight: _loginButtonHeight,
      privacyLabelOffsetY: valueOf(height - (536 + top), 10 + bottom),
      appPrivacyOriginLR: [46.5 + left + 20, 46.5 + right],
      checkboxOffsetY: valueOf(500 + top, height - bottom - 10 - 16),
      checkboxOffsetX: 46.5 + left,
      checkBoxWH: 18,
      appPrivacy: <NSAttributedString>[
        if (userAgreement != null)
          NSAttributedString(
            string: '《${userAgreement.name}》',
            attributes: {
              NSAttributedStringKey.link: userAgreement.url,
            },
          ),
        if (privacyPolicy != null)
          NSAttributedString(
            string: '《${privacyPolicy.name}》',
            attributes: {
              NSAttributedStringKey.link: privacyPolicy.url,
            },
          ),
      ],
      appPrivacyDemo: appPrivacyDemo,
      txMobliNumberOffsetY: valueOf(height - 308, height - 238) - top,
      numberTextAttributes: <NSAttributedStringKey, dynamic>{
        NSAttributedStringKey.font: const UIFont(
          fontSize: 34,
          fontWeight: FontWeight.w500,
        ),
        NSAttributedStringKey.foregroundColor: textColor,
      },
      webNavColor: privacyNavBgColor,
      webNavTitleAttrs: <NSAttributedStringKey, dynamic>{
        NSAttributedStringKey.font: const UIFont(
          fontSize: 17,
          fontWeight: FontWeight.w500,
        ),
      },
      loginBtnImgs: [
        UIImage.color(
          const Color(0xFF5F7CF8),
          size: loginButtonSize,
          radius: 7,
        ),
        UIImage.color(
          const Color(0xAA5F7CF8),
          size: loginButtonSize,
          radius: 7,
        ),
        UIImage.color(
          const Color(0x885F7CF8),
          size: loginButtonSize,
          radius: 7,
        ),
      ],
      uncheckedImg: uncheckedImgOf(context),
      checkedImg: checkedImgOf(context),
      sloganHidden: true,
      privacyUncheckAnimation: false,
      ignorePrivacyState: true,
      modalPresentationStyle: UIModalPresentationStyle.fullScreen,
      modalTransitionStyle: UIModalTransitionStyle.crossDissolve,
      customBackgroundView: UIViewGroup(
        id: r'background',
        background: background,
        width: width,
        height: height,
        children: [
          if (logo != null)
            UIImageView(
              id: r'logo',
              left: (width - 79) / 2,
              top: valueOf(97, 40) + top,
              width: 79,
              height: 79,
              src: logo,
              fit: BoxFit.fill,
            ),
          if (welcomeText != null)
            UITextView(
              id: r'welcome',
              left: (width - 150) / 2,
              top: valueOf(188.5, 131.5) + top,
              width: 148,
              height: 30,
              title: welcomeText,
              titleColor: textColor,
              textAlignment: TextAlignment.center,
              titleFont: const UIFont(
                fontSize: 22,
                fontWeight: FontWeight.w500,
              ),
            ),
          if (onSwitch != null)
            UIViewGroup(
              id: r'switch',
              left: (width - 150) / 2,
              top: valueOf(320, 240) + top,
              width: 150,
              height: 70,
              padding: const EdgeInsets.all(20),
              onPressed: onSwitch,
              children: [
                UIImageView(
                  id: r'switchIcon',
                  width: 13,
                  height: 13,
                  top: 1,
                  src: switchImgOf(context),
                ),
                UITextView(
                  id: r'switchText',
                  width: 110,
                  height: 15,
                  left: 19,
                  title: r'切换手机号',
                  titleColor: textColor,
                  titleFont: const UIFont(
                    fontSize: 16,
                    fontWeight: FontWeight.w500,
                  ),
                ),
              ],
            ),
          if (onClose != null)
            UIImageView(
              id: r'close',
              left: width - right - 65,
              top: top,
              width: 65,
              height: 65,
              padding: const EdgeInsets.all(25),
              fit: BoxFit.fill,
              src: closeImgOf(context),
              onPressed: onClose,
            ),
        ],
      ),
    );
  }

  /// [uncheckedImg]
  static UIImage uncheckedImgOf(BuildContext context) {
    return UIDecorator.loadAsset(
      context,
      Images.checkbox,
      package: r'tverify',
    );
  }

  /// [checkedImg]
  static UIImage checkedImgOf(BuildContext context) {
    return UIDecorator.loadAsset(
      context,
      Images.checkbox_on,
      package: r'tverify',
    );
  }

  /// switch
  static UIImage switchImgOf(BuildContext context) {
    return UIDecorator.loadAsset(
      context,
      Images.change,
      package: r'tverify',
    );
  }

  /// close
  static UIImage closeImgOf(BuildContext context) {
    return UIDecorator.loadAsset(
      context,
      Images.close,
      package: r'tverify',
    );
  }

  /// 多语言配置： AuthLanguageSimplifiedChinese ,
  /// 简体中文 AuthLanguageTraditionalChinese,
  /// 繁体中文 AuthLanguageEnglish, //英文
  final AuthLanguageType? appLanguageType;

  /// 隐私条款:数组（务必按顺序）要设置NSLinkAttributeName属性可以跳转协议
  /// 对象举例： NSAttributedString *str1 = [[NSAttributedString alloc]initWithString:@“百度协议” attributes:@{NSLinkAttributeName:@“https://www.baidu.com”}];
  final List<NSAttributedString>? appPrivacy;

  /// 隐私的内容模板：
  /// 1、全句可自定义但必须保留”&&默认&&“字段表明SDK默认协议,否则设置不生效
  /// 2、协议1和协议2的名称要与数组 str1 和 str2 … 里的名称 一样
  /// 3、必设置项（参考SDK的demo） appPrivacieDemo设置内容：登录并同意&&默认&&和&&百度协议&&、&&京东协议2&&登录并支持一键登录
  /// 展示： 登录并同意中国移动条款协议和百度协议1、京东协议2登录并支持一键登录
  final NSAttributedString? appPrivacyDemo;

  /// 隐私条款（包括check框）的左右边距
  final List<double>? appPrivacyOriginLR;

  /// 温馨提示: 窗口1模式下，自动隐藏系统导航栏,并生成一个UILabel 其frame为（0,0,窗口宽scaleW,44scaleW）
  /// 返回按钮的frame查看51属性备注,添加在UILabel的center.y位置
  final bool? authWindow;

  /// 品牌标签的字体大小
  final UIFont? brandLabelTextSize;

  /// 复选框相关属性
  final double? checkBoxWH;

  /// 未勾选隐私条款提示的自定义提示文案，提示功能默认关闭，该属性被合法赋值（非空，且最大长度为100的字符串）后打开提示功能。
  final String? checkTipText;

  /// 勾选框选X偏移量
  final double? checkboxOffsetX;

  /// 勾选框选Y偏移量，优先级高于checkboxOffsetY_B
  final double? checkboxOffsetY;

  /// 号勾选框选Y偏移量（基于底部）
  final double? checkboxOffsetYB;

  /// 复选框选中时图片
  final UIImage? checkedImg;

  /// 此属性支持半弹框方式与authWindow不同（此方式为UIPresentationController）
  /// 设置后自动隐藏切换按钮，该属性需要UIModalPresentationCustom（边缘弹窗模式下SDK默认设置）下生效
  final Size? controllerSize;

  /// 自定义窗口弧度 默认是10
  final double? cornerRadius;

  /// 自定义背景view 需要自定义背景图样式时使用，只在全屏模式下有效
  final UIView? customBackgroundView;

  /// 自定义view，需要根据屏幕位置传入相对应frame ,可添加多个
  final List<UIView>? customOtherLoginViews;

  /// 自定义顶部view，可自定义设计为导航栏样式
  final UIView? customTopLoginView;

  /// 边缘弹窗模式开关默认为no 全屏模式
  final bool? edgeWindow;

  /// 横竖屏默认属性
  final bool? faceOrientation;

  /// logo的图片设置
  final UIImage? iconImage;

  /// 是否创建自定义登录方式view，如添加QQ，微信等 默认YES 如需创建则将ifCreateCustomView 设置为YES
  final bool? ifCreateCustomView;

  /// 忽略隐私条款check框状态，登陆按钮一直可点击 默认:NO(不忽略)
  final bool? ignorePrivacyState;

  /// 是否显示默认加载loadingView,默认为YES;如需使用自定义LoadingView 请使用keywindow并添加 并在相关回调中取消
  final bool? isShowLoginLoadingView;

  /// 登录按钮高度
  /// 若需单独修改登录按钮的高度，宽度logBtnWidth不传值或者传0即可
  final double? logBtnHeight;

  /// 登录按钮Y偏移量（距离底部的偏移量）
  final double? logBtnOffsetY;

  /// 移动卡登录按钮的左右边距 注意:按钮呈现的宽度在竖屏时必须大于屏幕的一半,横屏时必须大于屏幕的三分之一
  /// 示例:@[@50,@70] 只能两个元素
  final List<double>? logBtnOriginLR;

  /// 修改登录按钮文本
  final NSAttributedString? logBtnText;

  /// 登入按钮背景颜色值 激活,失效,高亮;
  final List<Color>? loginBtnColors;

  /// 移动登入按钮背景图片，传图片对象数组，移动不可设置圆角 使用图片代替
  final List<UIImage>? loginBtnImgs;

  /// 自定义加载View，需配合isShowLoginLoadingView一起使用，设置为NO 则添加自定义View
  final UIView? loginLoadingView;

  /// LOGO图片frame
  final Rect? logoFrame;

  /// LOGO图片是否隐藏,默认显示 NO
  final bool? logoHidden;

  /// 模态展示样式设置属性
  final UIModalPresentationStyle? modalPresentationStyle;

  /// 窗口模式推出动画 UIModalTransitionStyleCoverVertical, 下推
  /// UIModalTransitionStyleFlipHorizontal,翻转 UIModalTransitionStyleCrossDissolve, 淡出
  final UIModalTransitionStyle? modalTransitionStyle;

  /// 号码栏X偏移量
  final double? numberOffsetX;

  /// 手机号码富文本属性
  final Map<NSAttributedStringKey, dynamic>? numberTextAttributes;

  /// 授权页面是否需要弹出动画
  final bool? presentAnimated;

  /// 页面弹出动画效果
  final RICHPresentationDirection? presentType;

  /// 修改隐私协议的文字颜色
  final Color? privacyColor;

  /// 隐私协议标签Y偏移量 该控件底部（bottom）相对于屏幕（safeArea）底部（bottom）的距离
  final double? privacyLabelOffsetY;

  /// 是否需要开启监听协议勾选状态  如果监听勾选协议必须实现方法
  final bool? privacyObserve;

  /// 协议是否打开--默认NO 勾选
  final bool? privacyState;

  /// 隐私条款增加抖动效果 默认:NO
  final bool? privacyUncheckAnimation;

  /// 自定义窗口高-缩放系数(屏幕高乘以系数) 默认是0.5
  final double? scaleH;

  /// 自定义窗口宽-缩放系数(屏幕宽乘以系数) 默认是0.8
  final double? scaleW;

  /// 品牌标签是否隐藏,默认显示 NO
  final bool? sloganHidden;

  /// 品牌logo图片及标签的Y偏移量(距离底部的位置)
  final double? sloganLabelOffsetY;

  /// 设置移动卡隐私协议提示语颜色
  final Color? sloganTextColor;

  /// 状态栏着色样式(隐藏导航栏时设置)
  final UIStatusBarStyle? statusBarStyle;

  /// 号码栏Y偏移量（基于底部）
  final double? txMobliNumberOffsetY;

  /// 复选框未选中时图片
  final UIImage? uncheckedImg;

  /// 登入页面背景图片
  final UIImage? viewBackImg;

  /// web协议界面导航标题栏颜色
  final Color? webNavColor;

  /// web协议界面导航返回图标(尺寸根据图片大小)
  final UIImage? webNavReturnImg;

  /// web协议界面导航标题字体属性设置
  /// 默认值：@{NSForegroundColorAttributeName: [UIColor whiteColor], NSFontAttributeName: [UIFont systemFontOfSize:16]}
  final Map<NSAttributedStringKey, dynamic>? webNavTitleAttrs;

  @override
  List<UIView> get _views {
    return [
      if (customBackgroundView != null) customBackgroundView!,
      ...?customOtherLoginViews,
      if (customTopLoginView != null) customTopLoginView!,
      if (loginLoadingView != null) loginLoadingView!,
    ];
  }

  @override
  Map<String, dynamic> toMap() {
    return <String, dynamic>{
      'appLanguageType': appLanguageType?.index,
      'appPrivacy': appPrivacy?.map((e) => e.toMap()).toList(),
      'appPrivacyDemo': appPrivacyDemo?.toMap(),
      'appPrivacyOriginLR': appPrivacyOriginLR,
      'authWindow': authWindow,
      'brandLabelTextSize': brandLabelTextSize?.toMap(),
      'checkBoxWH': checkBoxWH,
      'checkTipText': checkTipText,
      'checkboxOffsetX': checkboxOffsetX,
      'checkboxOffsetY': checkboxOffsetY,
      'checkboxOffsetY_B': checkboxOffsetYB,
      'checkedImg': checkedImg?.toMap(),
      'controllerSize': controllerSize?.toMap(),
      'cornerRadius': cornerRadius,
      'customBackgroundView': customBackgroundView?.toMap(),
      'customOtherLoginViews': customOtherLoginViews?.map((e) => e.toMap()).toList(),
      'customTopLoginView': customTopLoginView?.toMap(),
      'edgeWindow': edgeWindow,
      'faceOrientation': faceOrientation,
      'iconImage': iconImage?.toMap(),
      'ifCreateCustomView': ifCreateCustomView,
      'ignorePrivacyState': ignorePrivacyState,
      'isShowLoginLoadingView': isShowLoginLoadingView,
      'logBtnHeight': logBtnHeight,
      'logBtnOffsetY': logBtnOffsetY,
      'logBtnOriginLR': logBtnOriginLR,
      'logBtnText': logBtnText?.toMap(),
      'loginBtnColors': loginBtnColors?.map((e) => e.toMap()).toList(),
      'loginBtnImgs': loginBtnImgs?.map((e) => e.toMap()).toList(),
      'loginLoadingView': loginLoadingView?.toMap(),
      'logoFrame': logoFrame?.toMap(),
      'logoHidden': logoHidden,
      'modalPresentationStyle': modalPresentationStyle?.index,
      'modalTransitionStyle': modalTransitionStyle?.index,
      'numberOffsetX': numberOffsetX,
      'numberTextAttributes': numberTextAttributes?.toMap(),
      'presentAnimated': presentAnimated,
      'presentType': presentType?.index,
      'privacyColor': privacyColor?.toMap(),
      'privacyLabelOffsetY': privacyLabelOffsetY,
      'privacyObserve': privacyObserve,
      'privacyState': privacyState,
      'privacyUncheckAnimation': privacyUncheckAnimation,
      'scaleH': scaleH,
      'scaleW': scaleW,
      'sloganHidden': sloganHidden,
      'sloganLabelOffsetY': sloganLabelOffsetY,
      'sloganTextColor': sloganTextColor?.toMap(),
      'statusBarStyle': statusBarStyle?.index,
      'txMobliNumberOffsetY': txMobliNumberOffsetY,
      'uncheckedImg': uncheckedImg?.toMap(),
      'viewBackImg': viewBackImg?.toMap(),
      'webNavColor': webNavColor?.toMap(),
      'webNavReturnImg': webNavReturnImg?.toMap(),
      'webNavTitleAttrs': webNavTitleAttrs?.toMap(),
    };
  }
}

/// Modal presentation styles available when presenting view controllers.
enum UIModalPresentationStyle {
  /// A presentation style in which the presented view covers the screen.
  fullScreen,

  /// A presentation style that partially covers the underlying content.
  pageSheet,

  /// A presentation style that displays the content centered in the screen.
  formSheet,

  /// A presentation style where the content is displayed over another view controller’s content.
  currentContext,

  /// A custom view presentation style that is managed by a custom presentation controller and one or more custom animator objects.
  custom,

  /// A view presentation style in which the presented view covers the screen.
  overFullScreen,

  /// A presentation style where the content is displayed over another view controller’s content.
  overCurrentContext,

  /// A presentation style where the content is displayed in a popover view.
  popover,

  /// A presentation style that indicates no adaptations should be made.
  none,

  /// The default presentation style chosen by the system.
  automatic,
}

/// Transition styles available when presenting view controllers.
enum UIModalTransitionStyle {
  /// When the view controller is presented, its view slides up from the bottom of the screen.
  /// On dismissal, the view slides back down. This is the default transition style.
  coverVertical,

  /// When the view controller is presented, the current view initiates a horizontal 3D flip from right-to-left,
  /// resulting in the revealing of the new view as if it were on the back of the previous view. On dismissal,
  /// the flip occurs from left-to-right, returning to the original view.
  flipHorizontal,

  /// When the view controller is presented, the current view fades out while the new view fades in at the same time.
  /// On dismissal, a similar type of cross-fade is used to return to the original view.
  crossDissolve,

  /// When the view controller is presented, one corner of the current view curls up to reveal the presented view underneath.
  /// On dismissal, the curled up page unfurls itself back on top of the presented view.
  /// A view controller presented using this transition is itself prevented from presenting any additional view controllers.
  partialCurl,
}

/// 页面弹出动画效果
enum RICHPresentationDirection {
  /// 底部  present默认效果
  bottom,

  /// 右边  导航栏效果
  right,

  /// 上面
  top,

  /// 左边
  left,
}

/// Constants that describe the style of the device’s status bar.
enum UIStatusBarStyle {
  /// A status bar that automatically chooses light or dark content based on the user interface style.
  normal,

  /// A light status bar, intended for use on dark backgrounds.
  lightContent,

  /// A dark status bar, intended for use on light backgrounds.
  dartContent,
}

/// A string with associated attributes (such as visual style, hyperlinks, or accessibility data) for portions of its text.
final class NSAttributedString implements Codable {
  /// A string with associated attributes (such as visual style, hyperlinks, or accessibility data) for portions of its text.
  const NSAttributedString({
    required this.string,
    this.attributes,
  });

  /// The string for the new attributed string.
  final String string;

  /// The attributes for the new attributed string. For a list of attributes that you can include in this dictionary, see NSAttributedString.Key.
  final Map<NSAttributedStringKey, dynamic>? attributes;

  @override
  Map<String, dynamic> toMap() {
    return {
      'string': string,
      'attributes': attributes?.toMap(),
    };
  }
}

/// A string with associated attributes (such as visual style, hyperlinks, or accessibility data) for portions of its text.
enum NSAttributedStringKey {
  /// The font of the text.
  font,

  /// NSParagraphStyle, default defaultParagraphStyle
  paragraphStyle,

  /// UIColor, default blackColor
  foregroundColor,

  /// UIColor, default nil: no background
  backgroundColor,

  /// NSNumber containing integer, default 1: default ligatures, 0: no ligatures
  ligature,

  /// NSNumber containing floating point value, in points; amount to modify default kerning. 0 means kerning is disabled.
  kern,

  /// NSNumber containing floating point value, in points; amount to modify default tracking. 0 means tracking is disabled.
  tracking,

  /// NSNumber containing integer, default 0: no strikethrough
  strikethroughStyle,

  /// NSNumber containing integer, default 0: no underline
  underlineStyle,

  /// UIColor, default nil: same as foreground color
  strokeColor,

  /// NSNumber containing floating point value, in percent of font point size, default 0: no stroke; positive for stroke alone, negative for stroke and fill (a typical value for outlined text would be 3.0)
  strokeWidth,

  /// NSShadow, default nil: no shadow
  shadow,

  /// NSString, default nil: no text effect
  textEffect,

  /// NSTextAttachment, default nil
  attachment,

  /// NSURL (preferred) or NSString
  link,

  /// NSNumber containing floating point value, in points; offset from baseline, default 0
  baselineOffset,

  /// UIColor, default nil: same as foreground color
  underlineColor,

  /// UIColor, default nil: same as foreground color
  strikethroughColor,

  /// NSNumber containing floating point value; skew to be applied to glyphs, default 0: no skew
  obliqueness,

  /// NSNumber containing floating point value; log of expansion factor to be applied to glyphs, default 0: no expansion
  expansion,

  /// NSArray of NSNumbers representing the nested levels of writing direction overrides as defined by Unicode LRE, RLE, LRO, and RLO characters.  The control characters can be obtained by masking NSWritingDirection and NSWritingDirectionFormatType values.  LRE: NSWritingDirectionLeftToRight|NSWritingDirectionEmbedding, RLE: NSWritingDirectionRightToLeft|NSWritingDirectionEmbedding, LRO: NSWritingDirectionLeftToRight|NSWritingDirectionOverride, RLO: NSWritingDirectionRightToLeft|NSWritingDirectionOverride,
  writingDirection,

  /// An NSNumber containing an integer value.  0 means horizontal text.  1 indicates vertical text.  If not specified, it could follow higher-level vertical orientation settings.  Currently on iOS, it's always horizontal.  The behavior for any other value is undefined.
  verticalGlyphForm;

  /// 对应iOS的name
  String get rawValue {
    return switch (this) {
      foregroundColor => 'NSColor',
      _ => 'NS${name[0].toUpperCase()}${name.substring(1)}',
    };
  }
}
